// ignore_for_file: slash_for_doc_comments, camel_case_types, non_constant_identifier_names

import 'dart:convert';
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:encrypt/encrypt.dart' as encr; //aes加解密库
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:jwt_decode/jwt_decode.dart';
import 'package:slk/res/language/language.dart';
import 'package:slk/util/config.dart';
import 'package:slk/util/dq_dialog.dart';
import 'package:slk/util/httpfunc.dart';
import 'package:background_downloader/background_downloader.dart';

/**
 * 开发者控制整体日志是否输出
 */
bool enLogs() {
  return true;
}

enum dq_LogLevel_e {
  none, //0
  error, // 1
  warning, // 2
  info, // 3
  debug, // 4
  verbose, //5
}

dq_LogLevel_e _loglevel = dq_LogLevel_e.info;

void dqLog(dq_LogLevel_e level, String context) {
  if (enLogs() == false) {
    return;
  }

  switch (_loglevel) {
    case dq_LogLevel_e.error:
      if (level == dq_LogLevel_e.error) {
        debugPrint(context);
      }
      break;
    case dq_LogLevel_e.warning:
      if (level == dq_LogLevel_e.error || level == dq_LogLevel_e.warning) {
        debugPrint(context);
      }
      break;
    case dq_LogLevel_e.info:
      if (level == dq_LogLevel_e.error ||
          level == dq_LogLevel_e.warning ||
          level == dq_LogLevel_e.info) {
        debugPrint(context);
      }
      break;
    case dq_LogLevel_e.debug:
      if (level == dq_LogLevel_e.debug) {
        debugPrint(context);
      }
      break;
    case dq_LogLevel_e.verbose:
      debugPrint(context);
      break;
    default:
      break;
  }
}

void LOGD(String str) {
  dqLog(dq_LogLevel_e.debug, str);
}

void LOGE(String str) {
  dqLog(dq_LogLevel_e.error, str);
}

void LOGV(String str) {
  dqLog(dq_LogLevel_e.verbose, str);
}

void LOGW(String str) {
  dqLog(dq_LogLevel_e.warning, str);
}

void LOGI(String str) {
  dqLog(dq_LogLevel_e.info, str);
}

final key = encr.Key.fromUtf8("wx9feefe1cad96ec");
final iv = encr.IV.fromUtf8("da69bfaf2607d494");
//aes
encr.Encrypted netEncryptData(String data) {
  //mqtt和http通用加密

  final encrypter =
      encr.Encrypter(encr.AES(key, mode: encr.AESMode.cbc, padding: 'PKCS7'));
  final encrypted = encrypter.encrypt(data, iv: iv);
//  LOGI("加密数据: ${encrypted.base64}"); // 输出加密后的数据
  return encrypted;
}

String netDecryptData(String data) {
  //mqtt和http通用解密

  final encrypter =
      encr.Encrypter(encr.AES(key, mode: encr.AESMode.cbc, padding: 'PKCS7'));
  final decrypted = encrypter.decrypt64(data, iv: iv);
  // LOGI("解密数据: $decrypted");
  return decrypted;
}

void httpSend(Map<String, dynamic>? params, void Function(dynamic)? cb) async {
  if (params == null) {
    return;
  }

  bool netFlag = false;

  //http send
  Map<String, String> httpheaders = {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer  ${dq_configInfo()['accessToken']}',
    // 'X-Authorization': 'Bearer  ${dq_configInfo()['refreshToken']}',
  };

  //检查是否需要刷新 token
  if (dq_configInfo()['accessToken'] != '') {
    Map token = Jwt.parseJwt(dq_configInfo()['accessToken']);
    if (token != {}) {
      // LOGI('token --> $token');
      // jwt {UserName: 494798519@qq.com, iat: 1695789839, nbf: 1695789839, exp: 1702269839, iss: duoqin, aud: duoqin}
      int remainTime =
          token['exp'] * 1000 - DateTime.now().millisecondsSinceEpoch;

      //就剩下一个小时了
      if (remainTime < 60 * 60 * 1000) {
        httpheaders = {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer  ${dq_configInfo()['accessToken']}',
          'X-Authorization': 'Bearer  ${dq_configInfo()['refreshToken']}',
        };
      }
    }
  }

  LOGI('---> $params');

  //
  if (params['method'] == 'GET') {
    // 执行 HTTP 请求并处理响应

    String formatUrlData = '';
    params['data'].keys.forEach((e) {
      formatUrlData += '&$e=${params['data'][e]}';
    });
    formatUrlData += '&t=${DateTime.now().millisecondsSinceEpoch}';

    formatUrlData = formatUrlData.replaceFirst('&', '?');
    final url = Uri.parse('${params['url']}$formatUrlData');
    LOGI('url $url');
    http
        .get(
      url,
      headers: httpheaders,
    )
        .then((response) {
      // Handle the response
      LOGI('Response status code: ---> ${response.statusCode}'); //打印http响应状态码
      // LOGI('Response headers: ---> ${response.headers}'); //打印http响应状态码

      //刷新 token 如果存在的话
      Map header = response.headers;
      if (header['access-token'] != null) {
        LOGI('保存新的 accessToken');
        dq_configInfo()
            .update('accessToken', (value) => header['access-token']);
      }
      if (header['x-access-token'] != null) {
        dq_configInfo()
            .update('refreshToken', (value) => header['x-access-token']);

        LOGI('保存新的 refreshToken');
        dq_saveConfig();
      }

      netFlag = true;
      if (cb != null) {
        cb!(response.body);
        cb = null;
      }
    }).catchError((error) {
      // LOGI('网络异常 ${error}');
      if (error is SocketException) {
        // 处理网络连接问题
        LOGI('处理网络连接问题');
      } else if (error is HttpException) {
        // 处理 HTTP 请求失败
        LOGI('处理 HTTP 请求失败');
      } else if (error is FormatException) {
        // 处理无法解析的响应
        LOGI('处理无法解析的响应');
      } else {
        // 处理其他异常
        LOGI('GET 处理其他异常 ${error.toString()}');
        return;
      }

      Map errorMsg = {
        'code': 300,
        'msg': getUItext()['networkException'],
      };

      if (cb != null && netFlag == false) {
        cb!(jsonEncode(errorMsg).toString());
        cb = null;
      }
    });
  } else if (params['method'] == 'POST') {
    // 执行 HTTP 请求并处理响应
    final url = Uri.parse('${params['url']}?culture=${getLanguage()}');
    LOGI('url $url');

    http
        .post(
      url,
      headers: httpheaders,
      body: jsonEncode(params['data']),
    )
        .then((response) {
      // Handle the response
      LOGI('Response status code: ---> ${response.statusCode}'); //打印http响应状态码
      // LOGI('Response headers: ---> ${response.headers}'); //打印http响应状态码

      //刷新 token 如果存在的话
      Map header = response.headers;
      if (header['access-token'] != null) {
        LOGI('保存新的 accessToken');
        dq_configInfo()
            .update('accessToken', (value) => header['access-token']);
      }
      if (header['x-access-token'] != null) {
        dq_configInfo()
            .update('refreshToken', (value) => header['x-access-token']);

        LOGI('保存新的 refreshToken');
        dq_saveConfig();
      }

      netFlag = true;
      if (cb != null) {
        cb!(response.body);
        cb = null;
      }
    }).catchError((error) {
      if (error is SocketException) {
        // 处理网络连接问题
        LOGI('处理网络连接问题');
      } else if (error is HttpException) {
        // 处理 HTTP 请求失败
        LOGI('处理 HTTP 请求失败');
      } else if (error is FormatException) {
        // 处理无法解析的响应
        LOGI('处理无法解析的响应');
      } else {
        // 处理其他异常
        LOGI('POST 处理其他异常 ${error.toString()}');
        return;
      }

      Map errorMsg = {
        'code': 300,
        'msg': getUItext()['networkException'],
      };

      if (cb != null && netFlag == false) {
        cb!(jsonEncode(errorMsg).toString());
        cb = null;
      }
    });
  } else if (params['method'] == 'POSTFILE') {
    // 执行 HTTP 请求并处理响应
    final url = Uri.parse('${params['url']}?culture=${getLanguage()}');
    LOGI('url $url  data${params['data']}');

    ///     var uri = Uri.https('example.com', 'create');
    ///     var request = http.MultipartRequest('POST', uri)
    ///       ..fields['user'] = 'nweiz@google.com'
    ///       ..files.add(await http.MultipartFile.fromPath(
    ///           'package', 'build/package.tar.gz',
    ///           contentType: MediaType('application', 'x-tar')));
    ///     var response = await request.send();
    ///     if (response.statusCode == 200) print('Uploaded!');
    ///
    var request = http.MultipartRequest('POST', url)
      // ..fields['user'] = 'slk'
      ..files.add(
        await http.MultipartFile.fromPath(
          'files',
          '${params['data']['filePath']}',
        ),
      );
    var response = await request.send();
    response.stream.listen((value) {
      // 字节流转字符串
      String str = String.fromCharCodes(value);
      LOGI('response $str');

      if (cb != null) {
        cb!(str);
      }
    });
  }
}

/**
 * 相机使用
 */
class hyb_Camera {
  late CameraController _controller;
  late List<CameraDescription> _camera;

  hyb_Camera();

  /// 初始化相机
  Future init({required ResolutionPreset size}) async {
    // Obtain a list of the available cameras on the device.
    _camera = await availableCameras();

    int len = _camera.length;
    CameraDescription? camera;
    for (int i = 0; i < len; i++) {
      LOGI('当前一共有 $len 相机,  相机 $i 配置 -->  ${_camera[i]}');

      /// 只是用后置摄像头
      camera = _camera[i].lensDirection == CameraLensDirection.back
          ? _camera[i]
          : _camera[0];
    }

    /// 如果没找到后置摄像头,则使用第一个
    camera ??= _camera[0];

    _controller = CameraController(
      // Get a specific camera from the list of available cameras.
      camera,
      // Define the resolution to use.
      size,
    );
    return await _controller.initialize();
  }

  /// 获取相机控制,操作拍照
  CameraController get Controller => _controller;

  /// 获取相机列表
  List<CameraDescription> get Description => _camera;

  /// 关闭相机
  void close() {
    LOGI('关闭相机');
    _controller.dispose();
  }
}

class dq_cameraCreate extends StatefulWidget {
  Function(String)? cb;
  dq_cameraCreate(this.cb, {super.key});

  @override
  State<dq_cameraCreate> createState() => _dq_cameraCreateState();
}

class _dq_cameraCreateState extends State<dq_cameraCreate> {
  Size? _sceenSize;
  String _pageTitle = '', _imgPath = '', _imgUpLoadPath = '';
  showLoading? _loading;
  hyb_Camera? _camera;
  final List<String> _pictureBtnTips = ['拍照', '重新拍照', '上传中', '上传成功'];

  Widget _pictureBtnCreate(String name, Function()? onTap) {
    return Opacity(
      opacity: 0.618,
      child: InkWell(
        onTap: onTap,
        child: Container(
          decoration: BoxDecoration(
            color: Colors.blue[50],
            borderRadius: BorderRadius.circular(5),
          ),
          padding: EdgeInsets.all(
            _sceenSize!.width * 0.01,
          ),
          child: Center(
            child: Text(name),
          ),
        ),
      ),
    );
  }

  Future _initCamera() async {
    _camera ??= hyb_Camera();

    await _camera!.init(size: ResolutionPreset.medium);
  }

  void _takePicture(bool re) async {
    if (re == false) {
      _imgPath = '';

      setState(() {});
      return;
    }

    _loading ??= dq_showLoading(context, '图片上传中...');

    /// 拍照
    final img = await _camera!.Controller.takePicture();

    LOGI('文件地址 ${img.path} 文件名称:${img.name}');
    // /data/user/0/com.hyb.slk/cache/CAP852402265963261684.jpg
    _imgPath = img.path;

    /// 上传文件
    slk_uploadFile({'fileName': img.name, 'filePath': img.path}, (e) {
      LOGI('slk_uploadFile $e');

      if (_loading != null) {
        _loading!.close();
        _loading = null;
      }

      Map jsData = jsonDecode(e);
      if (jsData['code'] != 200) {
        dq_showmsg(context, '提示', jsData['msg'], null);
        return;
      }

      _imgUpLoadPath = jsData['data'][0]['downloadUrl'];
      LOGI('返回的图片下载地址 $_imgUpLoadPath');

      dq_showTips(context, '图片数据上传完成');

      widget.cb!(_imgUpLoadPath);

      // 刷新页面
      setState(() {});
    });
  }

  Widget _cameraCreate() {
    return ExpansionTile(
      title: Text('$_pageTitle 拍照'),
      initiallyExpanded: false,
      onExpansionChanged: (value) async {
        LOGI('onExpansionChanged $value');

        if (value == false) {
          _camera!.close();
          _camera = null;
        } else {
          await _initCamera();

          setState(() {});
        }
      },
      children: [
        Center(
          child: Stack(
            alignment: Alignment.center,
            children: [
              SizedBox(
                height: _sceenSize!.width * 0.618,
                width: _sceenSize!.width * 0.618,
                child: _imgPath.isNotEmpty
                    ? Image.file(
                        File(_imgPath),
                        fit: BoxFit.fitHeight,
                      )
                    : _camera != null
                        ? _camera!.Controller.buildPreview()
                        : const CircularProgressIndicator(),
              ),
              Positioned(
                left: _sceenSize!.width * 0.28,
                bottom: 10,
                child: _pictureBtnCreate(_pictureBtnTips[0], () {
                  _takePicture(true);
                }),
              ),
              Positioned(
                left: 10,
                top: 10,
                child: _pictureBtnCreate(_pictureBtnTips[1], () {
                  _takePicture(false);
                }),
              ),
            ],
          ),
        )
      ],
    );
  }

  @override
  void dispose() {
    if (_camera != null) {
      _camera!.close();
      _camera = null;
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    _sceenSize = MediaQuery.of(context).size;
    return _cameraCreate();
  }
}

/**
 * 下载文件
 */
class downloadFile {
  /// 临时保存下载文件地址
  String tempUrl;

  /// 下载任务
  DownloadTask? _task;

  /// 下载文件初始化
  downloadFile(this.tempUrl);

  /// 启动一个下载文件任务
  download(String url, String filename, Function(double)? onProgress) async {
    if (url.isEmpty && tempUrl.isEmpty) {
      if (onProgress != null) {
        onProgress(-1);
        onProgress = null;
      }
      return;
    }

    String urlTemp = url.isNotEmpty ? url : tempUrl;
    String fileNameTemp = urlTemp;
    int gap = fileNameTemp.lastIndexOf('/');
    fileNameTemp = fileNameTemp.substring(gap + 1);

    LOGI('下载内容 url:$url \n filename:$filename');

    _task ??= DownloadTask(
      url: urlTemp,
      filename: fileNameTemp,
      allowPause: true,
      baseDirectory: BaseDirectory.temporary,
    ); // define your _task
    final result = await FileDownloader().download(_task!, onStatus: (p0) {
      LOGI('onStatus $p0');
    }, onProgress: onProgress);

    LOGI('FileDownloader().download --> ${result.status}');

    if (result.status == TaskStatus.failed) {
      if (onProgress != null) {
        onProgress(-1);
        onProgress = null;
      }
    }
  }

  /// 关闭下载文件任务
  close() {
    FileDownloader().cancelTaskWithId(_task!.taskId);
  }

  /// 打开下载文件
  open() {
    FileDownloader().openFile(task: _task);
  }
}
